/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 */

import fse from 'fs-extra';
import path from 'path';

import { CommonConst } from '../../const/common-const.js';
import { PropertyConst } from '../../const/property-const.js';
import { FileUtil } from '../../utils/file-util.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';

const localPropertiesPath: string = path.resolve(process.cwd(), CommonConst.LOCAL_PROPERTIES);

/**
 * 读取项目目录下local.properties文件
 *
 * @since 2021-12-16
 */
export class Property {
  private _log: OhosLogger = OhosLogger.getLogger(Property.name);
  private _properties: Map<string, string> = new Map<string, string>();
  private readonly _isHarmonyOS: boolean;

  constructor(isHarmonyOS = true) {
    // read local.properties first and path next
    this._isHarmonyOS = isHarmonyOS;
    this._readFile().split(/\r?\n/).forEach(this._setProperty, this);
    this._properties.delete(PropertyConst.HWSDK_DIR);
    this._readPath();
  }

  /**
   * 读取当前命令行执行的路径下的local.properties的内容
   *
   * @returns {string} local.properties的内容
   */
  private _readFile(): string {
    if (this._isHarmonyOS || !fse.existsSync(localPropertiesPath)) {
      return '';
    }
    return fse.readFileSync(localPropertiesPath, { encoding: 'utf-8' });
  }

  getProperty(key: string): string {
    if (this._properties.has(key)) {
      const value = this._properties.get(key);
      return value ? value : '';
    }
    return '';
  }

  getSdkDir(): string {
    this.validatePath(PropertyConst.SDK_DIR, PropertyConst.ENV_OHOS_BASE_SDK_HOME);
    return this.getProperty(PropertyConst.SDK_DIR);
  }

  getHosSdkDir(): string {
    this.validatePath(PropertyConst.HWSDK_DIR, PropertyConst.DEVECO_SDK_HOME);
    return this.getProperty(PropertyConst.HWSDK_DIR);
  }

  getArkUIXSdkDir(): string {
    const arkUiDir: string | undefined = this._properties.get(PropertyConst.ARKUIX_SDK_DIR);
    if (!arkUiDir || !fse.existsSync(arkUiDir)) {
      this._log.printErrorExit(
        'NO_ARKUI_X_SDK_DIR',
        [PropertyConst.ARKUIX_SDK_DIR, PropertyConst.ENV_ARKUIX_SDK_HOME, localPropertiesPath]
      );
    }
    return this.getProperty(PropertyConst.ARKUIX_SDK_DIR);
  }

  private validatePath(propertyKey: string, pathKey: string): void {
    const location = this._properties.get(propertyKey);
    if (!location) {
      if (this._isHarmonyOS) {
        this._log.printErrorExit('INVALID_VALUE_OF_%S_IN_THESYSTEM_ENVIRONMENT_PATH', [pathKey]);
      } else {
        this._log.printErrorExit(
          'NO_SDK_HOME',
          [propertyKey, pathKey, localPropertiesPath],
          [[pathKey]]
        );
      }
    }
    if (!fse.existsSync(path.resolve(location!))) {
      if (this._isHarmonyOS) {
        this._log.printErrorExit('INVALID_VALUE_OF_%S_IN_THESYSTEM_ENVIRONMENT_PATH', [pathKey]);
      } else {
        this._log.printErrorExit(
          'NO_SDK_HOME',
          [propertyKey, pathKey, location],
          [[pathKey]]
        );
      }
    }
  }

  private _readPath(): void {
    // require sdk and node
    this._setPathIfNotExist(PropertyConst.SDK_DIR, process.env[PropertyConst.ENV_OHOS_BASE_SDK_HOME]);
    this._setPathIfNotExist(PropertyConst.NPM_DIR, process.env[PropertyConst.ENV_NODE_HOME]);
    this._setPathIfNotExist(PropertyConst.ARKUIX_SDK_DIR, process.env[PropertyConst.ENV_ARKUIX_SDK_HOME]);
    this._setPathIfNotExist(PropertyConst.HWSDK_DIR, process.env[PropertyConst.DEVECO_SDK_HOME]);
  }

  private _setPathIfNotExist(mapKey: string, envValue: string | undefined): void {
    if (this._properties.has(mapKey) || !envValue) {
      return;
    }
    this._properties.set(mapKey, FileUtil.normalizePathSeparator(envValue));
  }

  private _setProperty(text: string): void {
    if (!text || !text.trim()) {
      return;
    }
    const property = /^([^#=]+)(={0,1})(.*)$/.exec(text);
    if (property) {
      this._properties.set(property[1].trim(), FileUtil.normalizePathSeparator(property[3]).trimStart());
    }
  }
}
